package tota.tuples;

/**
 * <p>Title: TOTA</p>
 * <p>Description: TOTA</p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: DII - DISMI</p>
 * @author Marco Mamei
 * @version 1.0
 */

import java.util.*;
import emulator.utils.*;

import tuplespace.tuples.*;
import lime.tuples.*;

public class MetricTuple extends HopTuple
{
 private static final int REFRACTORY_TIME = 10;
 public int x = 0;
 public int y = 0;
 public int z = 0;

 /*****************************************************************************/
 /*         METHODS THAT MUST BE IMPLEMENTED AND ARE PART OF THE MODEL        */
 /*****************************************************************************/

 protected void changeTupleContent()
 {
  super.changeTupleContent();

  /************************************************** get the reference tuple */
  Vector v = tota.keyrdOneHop(this);

  if(v==null || v.size() == 0)
   return; // the init point is the center of the coordinates...

  MetricTuple baseTuple = (MetricTuple)v.elementAt(0);
  String basePeer = baseTuple.from;

  /****************************** get the relative coordinate to the basePeer */
  int base_x = 0;
  int base_y = 0;
  int base_z = 0;

  SensorTuple st = new SensorTuple("<sensor=radar><value=*>");
  st = (SensorTuple)tota.keyrd(st);

  String[] parsed = StaticUtilities.splitMessage(st.value,'[',']');
  for(int i=1;i<parsed.length;i++)
  {
   if(parsed[i].startsWith(basePeer))
   {
    int s = parsed[i].indexOf('@');
    String pointS = parsed[i].substring(s+1); // point
    int[] coordP = GenPoint.deserialize(pointS).getCoord();
    base_x = coordP[0];
    base_y = coordP[1];
    base_z = coordP[2];
    break;
   }
  }

  /******************************************************* change the content */
  this.x = baseTuple.x - base_x;
  this.y = baseTuple.y - base_y;
  this.z = baseTuple.z - base_z;
 }

 public void makeSubscriptions()
 {
  super.makeSubscriptions();
  SensorTuple st = new SensorTuple("<sensor=radar><value=*>");
  tota.subscribe(st, (ReactiveComponent)this,"RADAR");
 }

 public void react(String reaction, String event)
 {
  super.react(reaction, event);

  if(reaction.equalsIgnoreCase("RADAR"))
  {
   SensorTuple st = (SensorTuple)Tuple.deserialize(event);
   if(st.value.startsWith("[P]")) // this means that the peer actually moved
                                  // and not the world around...
   {
    if(this.hop==1)
    {
     tota.delete(this);
     scheduleRepropagation();
     return;
    }
    changeTupleContent();
    int[] color = getTupleColor();
    tota.setColor(color[0],color[1],color[2]);
    /*        here I have to do something to notofy that my value has changed */
    /* this is a fake store operation; the tuple is already stored... it is only
    useful to let the middleware trigger he right event. */
    tota.store(this);
   }
  }
  else if(reaction.equals("REPROPAGATE"))
  {
   tota.store(this);
   this.makeSubscriptions();
   int[] color = this.getTupleColor();
   tota.setColor(color[0],color[1],color[2]);
   this.delay = 0;
   propagate();
   tota.unsubscribe(Tuple.deserialize(event),this);
  }
 }

 /*****************************************************************************/
 /*                      TUPLE SPECIFIC METHODS                               */
 /*****************************************************************************/
 private void scheduleRepropagation()
 {
  SensorTuple st = new SensorTuple("<sensor=clock><value=*>");
  st = (SensorTuple)tota.keyrd(st);
  int currentTime = Integer.parseInt(st.value);
  st = new SensorTuple("<sensor=clock><value="+(currentTime+REFRACTORY_TIME)+">");
  tota.subscribe(st, this,"REPROPAGATE");
 }
}
